package vn.vfriends.id.servlet;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.openid4java.message.Message;
import org.openid4java.message.ParameterList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vn.vfriends.id.jpa.entity.User;
import vn.vfriends.id.openid.OpenIdProvider;

/**
 *
 * @author tuan@vfriends.vn
 */
@WebServlet(name = "openIdProviderServlet", urlPatterns = {"/op"})
public class OpenIdProviderServlet extends HttpServlet {

    private static Logger logger = LoggerFactory.getLogger(OpenIdProviderServlet.class);
    private ParameterList requestParameters;
    private static final String LOGIN_PAGE = "/login.vfs";

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (req.getParameterMap().isEmpty()) {
            // Empty request. Assume discovery request...
            logger.debug("Processing empty request. Assuming discovery request...");
            OpenIdProvider.sendDiscoveryResponse(resp);
        } else {
            requestParameters = new ParameterList(req.getParameterMap());
            OpenIdProvider.logRequestParameters(requestParameters);
            String mode = requestParameters.hasParameter("openid.mode") ? requestParameters.getParameterValue("openid.mode") : null;
            logger.info("Processing OpenID request '" + mode + "'...");
            // Save off the return_to value so when the user logs in successfully,
            /// we can redirect the browser there...
            // Crack the Request mode and process it accordingly...
            if ("associate".equals(mode)) {
                OpenIdProvider.processAssociationRequest(resp, requestParameters);
            } else if ("checkid_immediate".equals(mode)
                    || "checkid_setup".equals(mode)
                    || "check_authentication".equals(mode)) {
                // Check Session. If information is there, we're done. No need to login again.
                HttpSession session = req.getSession();
                if (session.getAttribute("LOGGED_USER") != null) {
                    // Create AuthResponse from session variables...
                    logger.info("********************************");
                    logger.info("* User is already logged in... *");
                    logger.info("********************************");
                    sendSuccessfulResponse(req, resp);
                } else {
                    //resp.sendRedirect(req.getContextPath() + LOGIN_PAGE + "?isopenid=true");
                    session.setAttribute("OPENID_PARAMS", requestParameters);
                    RequestDispatcher rd = req.getRequestDispatcher(LOGIN_PAGE);
                    rd.forward(req, resp);
                }
            } else {
                logger.error("Unknown request mode '" + mode + "'... Forcing login...");
            }
        }
    }

    private void sendSuccessfulResponse(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        Message authResponse = OpenIdProvider.buildAuthResponse(
                requestParameters,
                session.getAttribute("USER_SELECTED_ID").toString(),//getUserSelectedId(),
                session.getAttribute("USER_SELECTED_CLAIMED_ID").toString(),//getUserSelectedClaimedId(),
                (User)session.getAttribute("LOGGED_USER"));
        //getRequestCycle().setRedirect(false);// avoid the dreaded "Already redirecting" message...
        response.sendRedirect(authResponse.getDestinationUrl(true));
    }
}
